home *** CD-ROM | disk | FTP | other *** search
- Path: news.compuserve.com!newsmaster
- From: 76623,2065@compuserve.com (Bobby Martin)
- Newsgroups: comp.lang.c++
- Subject: Re: Here is my idea of callback code. However there are glitches can it be done better.
- Date: 19 Apr 1996 17:42:05 GMT
- Organization: CompuServe Incorporated
- Message-ID: <4l8j9d$781@arl-news-svc-3.compuserve.com>
- References: <Pine.SUN.3.91N2x.960418124921.4515B-100000@mumrik.nada.kth.se>
- Reply-To: 76623,2065@compuserve.com (Bobby Martin)
- NNTP-Posting-Host: dd35-197.compuserve.com
- X-Newsreader: IBM NewsReader/2 v1.03
-
- In <Pine.SUN.3.91N2x.960418124921.4515B-100000@mumrik.nada.kth.se>, Fredrik Vhrstrvm <d92-foh@nada.kth.se> writes:
- >
- >How do people write callbacks? The following code captures what I want
-
- <snip>
-
- Try this: create a base class for each signature of callback you desire which
- defines the interface to your callback function class (let's call it a functor).
- Then create a template child classes as needed to support various method
- signatures. I'll give you an example of the use of this so as to entice you to
- read the rather lengthy batch of code I've tacked to the end of this post.
-
- Before:
- typedef void (*VoidFunc)();
-
- void setCallback( VoidFunc aFunc);
-
- void hello();
-
- void junk()
- {
- setCallback( hello);
- ...
- }
-
- In this code, you can send in only C functions of signature 'void aFunc()'. But
- with functors, the following is possible:
-
- #include "voidfunc.hpp"
-
- void setCallback( VoidFunc aFunc);
-
- void hello();
-
- SomeList<int> listOfInts;
-
- void junk()
- {
- setCallback( VoidFunction( hello) );
- ...
- setCallback( VoidMemberFunc( listOfInts, SomeList<int>::add);
- ...
- }
-
- Use this base class as the type for any argument through which you wish to
- pass a callback or other pointer to function.
-
- Note that I'm not purporting that these code fragments are examples of good
- C++ code, they're just examples of how to use the functors. Due to a
- Borland bug, you will have to lose support for constant member functions
- under Borland by commenting out the constructor that takes a const member
- functions.
-
- class VoidFunc //base class for functors of signature 'void funcname();'
- {
- public:
- virtual void operator()() const =0; // allows use of object like a function
- const VoidFunc& operator*() const {return *this;} //allows (*aFunc)() syntax
- };
-
- class VoidFunction : public VoidFunc
- {
- private:
- typedef void (*VdFunc) ();
- VdFunc myFunc;
- public:
- VoidFunction( VdFunc aFunc = 0 ) : myFunc( aFunc ) {}
- virtual void operator()() const { myFunc(); }
- };
-
- template <class T>
- class VoidMemberFunc : public VoidFunc
- {
- private:
- typedef void (T::*Tfunc)();
- typedef void (T::*Tfuncc)() const; //support for const member functions
- const T* myObjc;
- T* myObj;
- Tfunc myFunc;
- Tfuncc myFuncc;
- public:
- VoidMemberFunc( const T& aObj, const Tfuncc& aFunc ) : myObj(0), myObjc( &aObj ), myFunc(0), myFuncc( aFunc ) {} //comment this line out under Borland
- VoidMemberFunc( T& aObj, const Tfunc& aFunc ) : myObjc(0), myObj( &aObj ), myFunc( aFunc ), myFuncc(0) {}
- void function( const Tfunc& aFunc ) { myFunc = aFunc; }
- void function( const Tfuncc& aFunc ) { myFuncc = aFunc; }
- void object( const T& aObj ) { myObjc = &aObj; myObj = 0;}
- void object( T& aObj ) { myObj = &aObj; myObjc = 0;}
- inline virtual void operator()() const;
- };
-
- template <class T>
- void VoidMemberFunc<T>::operator()() const
- {
- if( myObj )
- (myObj->*myFunc)();
- else if( myObjc )
- (myObjc->*myFuncc)();
- }
-
- Hope that helps,
- Bobby Martin
-